﻿/// <summary>
/// 类说明：公共的数据库访问访问类
/// 编码日期：2010-4-22
/// 编 码 人：苏飞
/// 联系方式：361983679  Email：sufei.1013@163.com  Blogs:http://www.sufeinet.com
/// 修改日期：2013-08-15
/// </summary>
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
namespace DotNet.Utilities
{
    /// <summary>
    /// The SqlHelper class is intended to encapsulate high performance, 
    /// scalable best practices for common uses of SqlClient.
    /// </summary>
    public abstract class SqlHelper
    {
        /// <summary>
        /// 带格式的分页SQL语句（第一页）
        /// 格式内容：0分页大小；1要选择的列；2表名；3选择条件(带where)；zzz4排序方式(带order by)
        /// </summary>
        protected const string SQL_PAGE_1 = "select top {0} {1} from {2} {3} {4}";
        /// <summary>
        /// 带格式的分页SQL语句（第二页以上适用）
        /// 格式内容：0分页大小；1要选择的列；2表名；3唯一列名（一般为主键）；4起始索引；5选择条件(带where)；6排序方式(带order by)；7选择条件(带and)
        /// </summary>
        protected const string SQL_PAGE_2 = "select top {0} {1} from {2} where {3} not in (select top {4} {3} from {2} {5} {6}) {7} {6}";  //0分页大小，1要选择的字段，页码

        /// <summary>
        /// 带格式的分页SQL语句，格式内容：0要选择的列，1表名，2唯一列名（一般为主键），3排序字段及方式，4选择条件，5起始行号，6结束行号
        /// </summary>
        protected const string SQL_PAGE_MSSQL2005 = @"SELECT {0} FROM {1} AS a INNER JOIN 
              (SELECT row_number_temp,{2} FROM 
                  (SELECT row_number() over(order by {3}) AS row_number_temp,{2} FROM {1} {4})
                  AS t WHERE row_number_temp BETWEEN {5} AND {6})
               AS b ON a.{2}=b.{2} ORDER BY b.row_number_temp";

        /// <summary>
        /// 带格式的表关联分页SQL语句，格式内容：0要选择的列，1表名，3排序字段及方式，4选择条件，5起始行号，6结束行号
        /// </summary>
        protected const string SQL_PAGE_MSSQL2005_JION = @"SELECT * FROM 
                    (SELECT ROW_NUMBER() OVER(ORDER BY {3}) AS row_number_temp,{0} FROM {1} {4})
                T WHERE row_number_temp BETWEEN {5} AND {6}";

        // Hashtable to store cached parameters
        private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

        #region ExecuteNonQuery
        /// <summary>
        /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="connectionString">a valid connection string for a SqlConnection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>an int representing the number of rows affected by the command</returns>
        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandTimeout = 60000;

            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                int val = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return val;
            }
        }

        /// <summary>
        /// Execute a SqlCommand (that returns no resultset) against an existing database connection 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="conn">an existing database connection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>an int representing the number of rows affected by the command</returns>
        public static int ExecuteNonQuery(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
            int val = cmd.ExecuteNonQuery();
            connection.Close();
            cmd.Parameters.Clear();
            return val;
        }

        /// <summary>
        /// Execute a SqlCommand (that returns no resultset) using an existing SQL Transaction 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="trans">an existing sql transaction</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>an int representing the number of rows affected by the command</returns>
        public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
            int val = cmd.ExecuteNonQuery();
            cmd.Parameters.Clear();
            return val;
        }

        #endregion

        #region ExecuteReader
        /// <summary>
        /// Execute a SqlCommand that returns a resultset against the database specified in the connection string 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="connectionString">a valid connection string for a SqlConnection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>A SqlDataReader containing the results</returns>
        public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            SqlConnection conn = new SqlConnection(connectionString);

            //we use a try/catch here because if the method throws an exception we want to 
            //close the connection throw code, because no datareader will exist, hence the 
            //commandBehaviour.CloseConnection will not work
            try
            {
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                cmd.Parameters.Clear();
                return rdr;
            }
            catch
            {
                conn.Close();
                throw;
            }

            //using (SqlConnection conn = new SqlConnection(connectionString))
            //{
            //    PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
            //    SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            //    cmd.Parameters.Clear();
            //    return rdr;
            //}
        }
        #endregion

        #region ExecuteScalar
        /// <summary>
        /// Execute a SqlCommand that returns the first column of the first record against the database specified in the connection string 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="connectionString">a valid connection string for a SqlConnection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
        public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                return ExecuteScalar(connection, cmdType, cmdText, commandParameters);
            }
        }

        /// <summary>
        /// Execute a SqlCommand that returns the first column of the first record against the database specified in the connection string 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="connectionString">a valid connection string for a SqlConnection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
        public static object ExecuteScalar(SqlTransaction trans, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
            object val = cmd.ExecuteScalar();
            cmd.Parameters.Clear();
            return val;
        }

        /// <summary>
        /// Execute a SqlCommand that returns the first column of the first record against an existing database connection 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="conn">an existing database connection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
        public static object ExecuteScalar(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
            object val = cmd.ExecuteScalar();
            connection.Close();
            cmd.Parameters.Clear();
            return val;
        }
        #endregion

        #region ExecuteDataSet
        /// <summary>
        /// Execute a SqlCommand that returns a resultset against the database specified in the connection string 
        /// using the provided parameters.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  DataSet ds = ExecuteDataSet(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
        /// </remarks>
        /// <param name="connectionString">a valid connection string for a SqlConnection</param>
        /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
        /// <param name="commandText">the stored procedure name or T-SQL command</param>
        /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
        /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
        public static DataSet ExecuteDataSet(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                SqlDataAdapter myAdapter = new SqlDataAdapter(cmd);
                DataSet myDataSet = new DataSet();
                myAdapter.Fill(myDataSet);
                cmd.Parameters.Clear();
                return myDataSet;
            }
        }
        #endregion

        /// <summary>
        /// add parameter array to the cache
        /// </summary>
        /// <param name="cacheKey">Key to the parameter cache</param>
        /// <param name="cmdParms">an array of SqlParamters to be cached</param>
        public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters)
        {
            parmCache[cacheKey] = commandParameters;
        }

        /// <summary>
        /// Retrieve cached parameters
        /// </summary>
        /// <param name="cacheKey">key used to lookup parameters</param>
        /// <returns>Cached SqlParamters array</returns>
        public static SqlParameter[] GetCachedParameters(string cacheKey)
        {
            SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];

            if (cachedParms == null)
                return null;

            SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];

            for (int i = 0, j = cachedParms.Length; i < j; i++)
                clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

            return clonedParms;
        }

        /// <summary>
        /// Prepare a command for execution
        /// </summary>
        /// <param name="cmd">SqlCommand object</param>
        /// <param name="conn">SqlConnection object</param>
        /// <param name="trans">SqlTransaction object</param>
        /// <param name="cmdType">Cmd type e.g. stored procedure or text</param>
        /// <param name="cmdText">Command text, e.g. Select * from Products</param>
        /// <param name="cmdParms">SqlParameters to use in the command</param>
        private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
        {
            if (conn.State != ConnectionState.Open)
                conn.Open();

            cmd.Connection = conn;
            cmd.CommandText = cmdText;

            if (trans != null)
                cmd.Transaction = trans;

            cmd.CommandType = cmdType;

            if (cmdParms != null)
            {
                foreach (SqlParameter parm in cmdParms)
                    cmd.Parameters.Add(parm);
            }
        }


        /// <summary>
        /// 返回按分页大小返回指定页码的指定字段的SQL语句
        /// 注意：仅SqlServer2005以上可用
        /// </summary>
        /// <param name="dbTableName">数据表名称</param>
        /// <param name="IdColumName">唯一列名（一般为主键）</param>
        /// <param name="conditionSql">指定条件(不包含where)</param>
        /// <param name="selectFields">要返回的字段，为空则返回所有字段</param>
        /// <param name="orderBy">排序方式，不包含order by</param>
        /// <param name="pageSize">分页大小--每页包含的记录数</param>
        /// <param name="pageIndex">页码--要获取第几页的记录</param>
        /// <returns>返回按分页大小返回指定页码的指定字段的SQL语句</returns>
        public static string GetPageSQL_MSSQL2005(string dbTableName, string IdColumName, string conditionSql, string selectFields, string orderBy, int pageSize, int pageIndex)
        {
            if (pageSize <= 0) pageSize = 10;
            if (pageIndex <= 0) pageIndex = 1;
            //如果是第一页,则直接使用top语句
            if (pageIndex == 1) return GetPageSQL(dbTableName, IdColumName, conditionSql, selectFields, orderBy, pageSize, pageIndex);

            if (selectFields.Trim() == "") selectFields = "a.*";
            else selectFields = ((string)("a." + selectFields)).Replace(",", ",a.");
            if (orderBy.Trim() == "") orderBy = IdColumName;
            if (conditionSql.Trim() != "") conditionSql = "where " + conditionSql;

            StringBuilder sqlSb = new StringBuilder();
            sqlSb.AppendFormat(SQL_PAGE_MSSQL2005, selectFields, dbTableName, IdColumName, orderBy, conditionSql, (pageIndex - 1) * pageSize + 1, pageIndex * pageSize);
            return sqlSb.ToString();
        }

        /// <summary>
        /// 返回按分页大小返回指定页码的指定字段的SQL语句
        /// SqlServer2000/SqlServer2005可用
        /// </summary>
        /// <param name="dbTableName">数据表名称</param>
        /// <param name="IdColumName">唯一列名（一般为主键）</param>
        /// <param name="conditionSql">指定条件(不包含where)</param>
        /// <param name="selectFields">要返回的字段，为空则返回所有字段</param>
        /// <param name="orderBy">排序方式，不包含order by</param>
        /// <param name="pageSize">分页大小--每页包含的记录数</param>
        /// <param name="pageIndex">页码--要获取第几页的记录</param>
        /// <returns>返回按分页大小返回指定页码的指定字段的SQL语句</returns>
        public static string GetPageSQL(string dbTableName, string IdColumName, string conditionSql, string selectFields, string orderBy, int pageSize, int pageIndex)
        {
            if (pageSize <= 0) pageSize = 10;
            if (pageIndex <= 0) pageIndex = 1;
            if (selectFields.Trim() == "") selectFields = "*";
            StringBuilder sqlSb = new StringBuilder();
            if (pageIndex > 1) sqlSb.AppendFormat(SQL_PAGE_2, pageSize, selectFields, dbTableName, IdColumName, pageSize * (pageIndex - 1), conditionSql.Trim() == "" ? "" : (" where " + conditionSql), orderBy.Trim() == "" ? "" : (" order by " + orderBy), conditionSql.Trim() == "" ? "" : (" and " + conditionSql));
            else sqlSb.AppendFormat(SQL_PAGE_1, pageSize, selectFields, dbTableName, conditionSql.Trim() == "" ? "" : (" where " + conditionSql), orderBy.Trim() == "" ? "" : (" order by " + orderBy));
            return sqlSb.ToString();
        }

        /// <summary>
        /// 返回按分页大小返回指定页码的指定字段的SQL语句
        /// 注意：仅SqlServer2005以上可用
        /// </summary>
        /// <param name="dbTableName">数据表名称</param>
        /// <param name="IdColumName">唯一列名（一般为主键）</param>
        /// <param name="conditionSql">指定条件(不包含where)</param>
        /// <param name="selectFields">要返回的字段，为空则返回所有字段</param>
        /// <param name="orderBy">排序方式，不包含order by</param>
        /// <param name="pageSize">分页大小--每页包含的记录数</param>
        /// <param name="pageIndex">页码--要获取第几页的记录</param>
        /// <returns>返回按分页大小返回指定页码的指定字段的SQL语句</returns>
        public static string GetPageSQL_MSSQL2005_JOIN(string dbTableName, string IdColumName, string conditionSql, string selectFields, string orderBy, int pageSize, int pageIndex)
        {
            if (pageSize <= 0) pageSize = 10;
            if (pageIndex <= 0) pageIndex = 1;
            //如果是第一页,则直接使用top语句
            if (pageIndex == 1) return GetPageSQL(dbTableName, IdColumName, conditionSql, selectFields, orderBy, pageSize, pageIndex);

            if (selectFields.Trim() == "") selectFields = "*";
            if (orderBy.Trim() == "") orderBy = IdColumName;
            if (conditionSql.Trim() != "") conditionSql = "where " + conditionSql;

            StringBuilder sqlSb = new StringBuilder();
            sqlSb.AppendFormat(SQL_PAGE_MSSQL2005_JION, selectFields, dbTableName, IdColumName, orderBy, conditionSql, (pageIndex - 1) * pageSize + 1, pageIndex * pageSize);
            return sqlSb.ToString();
        }

        #region 由Object取值
        /// <summary>
        /// 取得Int16值
        /// </summary>
        public static Int16? GetInt16(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                short result;
                if (Int16.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得UInt16值
        /// </summary>
        public static UInt16? GetUInt16(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                ushort result;
                if (UInt16.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得Int值
        /// </summary>
        public static int? GetInt32(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                int result;
                if (int.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得long值
        /// </summary>
        public static long? GetInt64(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                long result;
                if (long.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得UInt64值
        /// </summary>
        public static ulong? GetULong(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                ulong result;
                if (ulong.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得byte值
        /// </summary>
        public static byte? GetByte(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                byte result;
                if (byte.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得sbyte值
        /// </summary>
        public static sbyte? GetSByte(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                sbyte result;
                if (sbyte.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获得Long值
        /// </summary>
        public static long? GetLong(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                long result;
                if (long.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得Decimal值
        /// </summary>
        public static decimal? GetDecimal(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                decimal result;
                if (decimal.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得float值
        /// </summary>
        public static float? GetFloat(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                float result;
                if (float.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null; ;
            }
        }

        /// <summary>
        /// 取得double值
        /// </summary>
        public static double? GetDouble(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                double result;
                if (double.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得Guid值
        /// </summary>
        public static Guid? GetGuid(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                try
                {
                    Guid result = new Guid(obj.ToString());
                    return result;
                }
                catch
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得DateTime值
        /// </summary>
        public static DateTime? GetDateTime(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                DateTime result;
                if (DateTime.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得bool值
        /// </summary>
        public static bool? GetBoolean(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                bool result;
                if (bool.TryParse(obj.ToString(), out result))
                    return result;
                else
                    return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得byte[]
        /// </summary>
        public static byte[] GetBinary(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                return (byte[])obj;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 取得string值
        /// </summary>
        public static string GetString(object obj)
        {
            if (obj != null && obj != DBNull.Value)
            {
                return obj.ToString();
            }
            else
            {
                return null;
            }
        }
        #endregion

    }
}


